--===================================================================================--
--[[                                                                               ]]--
--[[  iClass - A base to quickly create classes without fiddling with metatables.  ]]--
--[[                                                                               ]]--
--[[  How To:                                                                      ]]--
--[[                                                                               ]]--
--[[  1. Create a class using class(name).                                         ]]--
--[[  2. Create the __init() function, which initializes an instance.              ]]--
--[[  3. Do whatever the fuck you want. Hint: Like adding functions. :o            ]]--
--[[  4. Initialize a class using name(args)                                       ]]--
--[[  5. Do whatever the fuck you want with your instance                          ]]--
--[[  6. You're done, get the fuck out. I have better things to do than writing    ]]--
--[[  	 silly how-to's for downies. <3                                            ]]--
--[[                                                                               ]]--
--[[   See below for an example                                                    ]]--
--[[                                                                               ]]--
--===================================================================================--

--[[ The Class ]]--

class, metatable, class_metatable = {}, {}, {}
class_metatable.__index = class_metatable
setmetatable(class, metatable)

function class_metatable:__call(...)
	local object = { __type = "instance" }
	object.GetClass = function() return self.__class end
	object.GetClassName = function() return self.__class.__name end
	setmetatable(object, self)
	if object.__init then object:__init(...) end
	return object
end

function metatable:__call(...)
	local class = { __type = "class" }
	class.__class, class.__index, class.__name = class, class, ({...})[1]
	class.GetClass = function() return self.__class end
	class.GetClassName = function() return self.__class.__name end
	setmetatable(class, class_metatable)

	_G[class.__name] = class
	return class
end

--[[ Other Functions ]]--

local _type = type -- Save old type() function.
function type(object)
	return _type(object) == "table" and object.__type or _type(object)
end

--[[ Test ]]--

if true then return end -- Change to false to test.

class "Bank" -- Or class("Bank")

function Bank:__init(accountHolder, balance, bankName)
	self.accountHolder = accountHolder
	self.balance = balance
	self.bankName = bankName
	d("Thank you for opening an account with us, "..accountHolder..". Your initial balance is $"..tostring(balance))
end

function Bank:Deposit(amount)
	self.balance = self.balance + amount
	return "You deposited $"..tostring(amount).." into your bank account. You now have "..tostring(self:GetBalance())
end

function Bank:Withdraw(amount)
	self.balance = self.balance - amount
	return "You withdrew $"..tostring(amount).." from your bank account. You now have "..tostring(self:GetBalance())
end

function Bank:Transfer(target, amount)
	if target:GetClassName() == "Bank" then
		self.balance = self.balance - amount
		target.balance = target.balance + amount
		return "You transfered $"..tostring(amount).." to "..target.accountHolder.."'s bank account. You now have "..tostring(self:GetBalance())
	end

	return "Your target was not a valid bank account. Please try again."
end

function Bank:GetBalance()
	return self.balance
end

function Bank:ImAL33tHackerAndICanEditMyBalanceHashtagYolo(amount)
	self.balance = 0 -- Oops, something has gone wrong!
	return "Done, you now have $"..tostring(amount)
end

-- Class done, now let's test have fun with it.

BankA = Bank("Mr. A", 1000)
BankB = Bank("Ms. B", 1000)

d(BankA:Deposit(1)) -- I don't have more than $1.
d(BankA:Withdraw(1)) -- Need my $1.
d(BankA:Transfer(BankB, 100)) -- Hookers be expensive.
d(BankA:GetBalance()) -- Woohoo! I can get nine more hookers!
d(BankA:ImAL33tHackerAndICanEditMyBalanceHashtagYolo(1000000)) -- Imma be rich, yo! Getting them bitches all night!
d(BankA:GetBalance()) -- Fuck...